package top.jiangqiang.crawler.core.client;

import org.dromara.hutool.core.thread.ExecutorBuilder;
import org.dromara.hutool.core.thread.NamedThreadFactory;
import org.jetbrains.annotations.NotNull;
import top.jiangqiang.crawler.core.config.GlobalCrawlerConfig;
import top.jiangqiang.crawler.core.constants.BodyMergeStrategy;
import top.jiangqiang.crawler.core.constants.HeaderMergeStrategy;
import top.jiangqiang.crawler.core.constants.QueryParameterMergeStrategy;
import top.jiangqiang.crawler.core.entities.Crawler;
import top.jiangqiang.crawler.core.handler.ResultHandler;
import top.jiangqiang.crawler.core.http.HttpService;
import top.jiangqiang.crawler.core.http.OkHttpService;
import top.jiangqiang.crawler.core.http.entities.QueryParameters;
import top.jiangqiang.crawler.core.http.entities.RequestHeader;
import top.jiangqiang.crawler.core.http.entities.RequestLine;
import top.jiangqiang.crawler.core.http.entities.body.HttpBody;
import top.jiangqiang.crawler.core.recorder.RecorderService;
import top.jiangqiang.crawler.core.recorder.impl.DefaultRecorderService;

import java.util.Objects;
import java.util.concurrent.ThreadPoolExecutor;

public interface CrawlerService {
    /**
     * 获取种子记录器服务
     *
     * @return
     */
    @NotNull
    RecorderService getRecorderService();

    @NotNull
    GlobalCrawlerConfig initGlobalCrawlerConfig();
    /**
     * @return 获取请求服务
     */
    @NotNull
    default HttpService initHttpService() {
        return new OkHttpService(getGlobalCrawlerConfig());
    }

    /**
     * @return 获取请求服务
     */
    @NotNull
    HttpService getHttpService();

    /**
     * 获取种子记录器服务
     *
     * @return
     */
    @NotNull
    default RecorderService initRecorderService() {
        return new DefaultRecorderService();
    }

    /**
     * 获取全局配置
     *
     * @return
     */
    @NotNull
    GlobalCrawlerConfig getGlobalCrawlerConfig();

    /**
     * 结果处理
     *
     * @return
     */
    @NotNull
    ResultHandler initResultHandler();

    /**
     * 结果处理
     *
     * @return
     */
    @NotNull
    ResultHandler getResultHandler();

    /**
     * 初始化任务调度的线程池
     *
     * @return
     */
    @NotNull
    default ThreadPoolExecutor initRequestExecutorService() {
        return ExecutorBuilder.of()
                .setCorePoolSize(getGlobalCrawlerConfig().getRequestThreads() / 2)
                .setMaxPoolSize(getGlobalCrawlerConfig().getRequestThreads())
                .setThreadFactory(new NamedThreadFactory("crawler-http-thread-pool", false))
                .build();
    }

    /**
     * 获取任务调度的线程池
     *
     * @return
     */
    @NotNull
    ThreadPoolExecutor getRequestExecutorService();

    /**
     * @return 初始化处理响应的线程池
     */
    @NotNull
    default ThreadPoolExecutor initProcessingExecutorService() {
        return ExecutorBuilder.of()
                .setCorePoolSize(getGlobalCrawlerConfig().getProcessingThreads() / 2)
                .setMaxPoolSize(getGlobalCrawlerConfig().getProcessingThreads())
                .setThreadFactory(new NamedThreadFactory("crawler-processing-thread-pool", false))
                .build();
    }

    /**
     * 获取处理响应的线程池
     *
     * @return
     */
    @NotNull
    ThreadPoolExecutor getProcessingExecutorService();

    /**
     * @param crawler
     * @return
     */
    @NotNull
    Runnable getTask(Crawler crawler);

    /**
     * 启动爬虫任务
     */
    void start();
    default void merge(Crawler crawler) {
        GlobalCrawlerConfig globalConfig = getGlobalCrawlerConfig();
        mergeLine(crawler, globalConfig.getRequestLine());
        mergeHeader(crawler, globalConfig.getRequestHeader(), globalConfig.getHeaderStrategy());
        mergeBody(crawler, globalConfig.getRequestBody(), globalConfig.getBodyStrategy());
        mergeQueryParameters(crawler, globalConfig.getQueryParameters(), globalConfig.getQueryParameterMergeStrategy());
    }

    /**
     * @param crawler     种子不存在请求行时使用全局替代
     * @param requestLine 全局请求行
     */
    default void mergeLine(Crawler crawler, RequestLine requestLine) {
        if (crawler.getRequestLine() == null) {
            crawler.setRequestLine(Objects.requireNonNullElseGet(requestLine, RequestLine::new));
        }
    }

    default void mergeHeader(Crawler crawler, RequestHeader requestHeader, HeaderMergeStrategy headerStrategy) {
        if (requestHeader == null) {
            return;
        }
        RequestHeader dist = crawler.getRequestHeader();
        if (dist == null) {
            dist = new RequestHeader();
            crawler.setRequestHeader(dist);
        }
        switch (headerStrategy) {
            case MERGE:
                dist.mergeHeader(requestHeader);
                break;
            case REPLACE:
                dist = new RequestHeader();
                dist.mergeHeader(requestHeader);
                crawler.setRequestHeader(dist);
                break;
            case AUTO_SELECT:
                if (dist.isEmpty()) {
                    dist.mergeHeader(requestHeader);
                }
                break;
            default:
                // 处理其他情况
                break;
        }
    }

    /**
     * @param crawler      如果当前没有请求体，则不合并
     * @param httpBody     全局请求体中的参数
     * @param bodyStrategy 合并策略
     */
    default void mergeBody(Crawler crawler, HttpBody<?> httpBody, BodyMergeStrategy bodyStrategy) {
        if (BodyMergeStrategy.MERGE.equals(bodyStrategy)) {
            HttpBody<?> requestBody = crawler.getRequestBody();
            if (requestBody instanceof HttpBody<?> httpBodyFromMap) {
                httpBodyFromMap.merge(httpBody);
            }
        }
    }

    default void mergeQueryParameters(Crawler crawler, QueryParameters queryParameters, QueryParameterMergeStrategy queryParameterMergeStrategy) {
        if (QueryParameterMergeStrategy.MERGE.equals(queryParameterMergeStrategy)) {
            if (crawler.getQueryParameters() != null) {
                crawler.getQueryParameters().merge(queryParameters);
            } else {
                crawler.setQueryParameters(queryParameters);
            }
        }
    }

}
